#include <iostream.h>
#include <string>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include"ofxNetwork.h"
using namespace std;

#include "networkConstants.h"

string ofToString(double value, int precision = 0){
	stringstream sstr;
	sstr << fixed << setprecision(precision) << value;
	return sstr.str();
}

int getElapsedTimeMillis(){
	return 1000*100*(clock()/(float)CLOCKS_PER_SEC);
}

ofxTCPServer TCP;
vector<int> clientTimers;

class Player {
public:
	int client;
	float posX;
};

class Ball {
public:
	float posX, posY;
};

vector<Player> players;
Ball ball;
int dT;
int timeSinceClientUpdate;

int numPlayers(){
	return players.size();
}

int main(int argc, char *argv[])
{
	TCP.setup(11995);
	while(1){
		while(TCP.getNumClients() > clientTimers.size()){
			clientTimers.push_back(getElapsedTimeMillis());
		}
		for(int i = 0; i < TCP.getNumClients(); i++){	
			if(TCP.isClientConnected(i)){
				if(getElapsedTimeMillis()-clientTimers[i] > 5000){
					//Client has timed out. Delete it!
					cout<<"Client "<<TCP.getClientIP(i)<<" doesn't respond.. Goodbye!"<<endl;
					TCP.disconnectClient(i);
					
					for(int u=0;u<players.size();u++){
						if(players[u].client == i){
							//Delete the player in the array
							players.erase(players.begin()+u);
							if(numPlayers()>0){
								//Change player numbers on other clients
								for(int p=0;p<numPlayers();p++){
									TCP.sendAdr(i,ADR_SET_PLAYER_NUMBER,ofToString(p));
								}
							}
						}
					}
				}
				
				timeSinceClientUpdate += getElapsedTimeMillis()- dT;
				if(timeSinceClientUpdate > 100){
					for(int u=0;u<players.size();u++){
						if(players[u].client != i){
							TCP.sendAdr(i, ADR_PLAYER_POSX, ofToString(u)+ofToString(players[u].posX,5));
						}
					}
					timeSinceClientUpdate = 0;
				}
				
				string str = TCP.receive(i);
				if( str.length() > 0 ){
					//cout<<"Msg received: "<<str<<endl;
					switch (str[0]) {
						case ADR_HANDSHAKE:
							if(str.substr(1).compare("player")==0){
								//Client wants to be player
								if(numPlayers() < 2){
									cout<<"Handshake with player from IP "<<TCP.getClientIP(i)<<endl;
									Player nPlayer;
									nPlayer.client = i;		
									players.push_back(nPlayer);
									TCP.sendAdr(i, ADR_HANDSHAKE,ofToString(numPlayers()));
								}
							} else {
								TCP.sendAdr(i, ADR_HANDSHAKE,"");
							}
							break;
						case ADR_PING:
							//Client pings, and we send the value back (for latency calculation)
							clientTimers[i] = getElapsedTimeMillis();
							TCP.send(i, str);
							break;
						case ADR_PLAYER_POSX:
							int p = atoi(str.substr(1, 1).c_str());
							if(p<numPlayers()){
								players[p].posX = strtod(str.substr(2).c_str(), NULL);
								//cout<<"Set pos to "<<players[p].posX <<endl;
							}
							break;
						default:
							break;
					}
				}
			}


	 	}	

		dT = getElapsedTimeMillis();
		usleep(10 * 1000);
	}

	return 0;
}

